﻿using System;
using System.Collections.Generic;

namespace UniRx.Operators
{
	// Token: 0x0200024E RID: 590
	internal class BufferObservable<T> : OperatorObservableBase<IList<T>>
	{
		// Token: 0x06000D8F RID: 3471 RVA: 0x000403F4 File Offset: 0x0003E7F4
		public BufferObservable(IObservable<T> source, int count, int skip) : base(source.IsRequiredSubscribeOnCurrentThread<T>())
		{
			this.source = source;
			this.count = count;
			this.skip = skip;
		}

		// Token: 0x06000D90 RID: 3472 RVA: 0x00040417 File Offset: 0x0003E817
		public BufferObservable(IObservable<T> source, TimeSpan timeSpan, TimeSpan timeShift, IScheduler scheduler) : base(scheduler == Scheduler.CurrentThread || source.IsRequiredSubscribeOnCurrentThread<T>())
		{
			this.source = source;
			this.timeSpan = timeSpan;
			this.timeShift = timeShift;
			this.scheduler = scheduler;
		}

		// Token: 0x06000D91 RID: 3473 RVA: 0x00040451 File Offset: 0x0003E851
		public BufferObservable(IObservable<T> source, TimeSpan timeSpan, int count, IScheduler scheduler) : base(scheduler == Scheduler.CurrentThread || source.IsRequiredSubscribeOnCurrentThread<T>())
		{
			this.source = source;
			this.timeSpan = timeSpan;
			this.count = count;
			this.scheduler = scheduler;
		}

		// Token: 0x06000D92 RID: 3474 RVA: 0x0004048C File Offset: 0x0003E88C
		protected override IDisposable SubscribeCore(IObserver<IList<T>> observer, IDisposable cancel)
		{
			if (this.scheduler == null)
			{
				if (this.skip == 0)
				{
					return new BufferObservable<T>.Buffer(this, observer, cancel).Run();
				}
				return new BufferObservable<T>.Buffer_(this, observer, cancel).Run();
			}
			else
			{
				if (this.count > 0)
				{
					return new BufferObservable<T>.BufferTC(this, observer, cancel).Run();
				}
				if (this.timeSpan == this.timeShift)
				{
					return new BufferObservable<T>.BufferT(this, observer, cancel).Run();
				}
				return new BufferObservable<T>.BufferTS(this, observer, cancel).Run();
			}
		}

		// Token: 0x040007AA RID: 1962
		private readonly IObservable<T> source;

		// Token: 0x040007AB RID: 1963
		private readonly int count;

		// Token: 0x040007AC RID: 1964
		private readonly int skip;

		// Token: 0x040007AD RID: 1965
		private readonly TimeSpan timeSpan;

		// Token: 0x040007AE RID: 1966
		private readonly TimeSpan timeShift;

		// Token: 0x040007AF RID: 1967
		private readonly IScheduler scheduler;

		// Token: 0x0200024F RID: 591
		private class Buffer : OperatorObserverBase<T, IList<T>>
		{
			// Token: 0x06000D93 RID: 3475 RVA: 0x00040516 File Offset: 0x0003E916
			public Buffer(BufferObservable<T> parent, IObserver<IList<T>> observer, IDisposable cancel) : base(observer, cancel)
			{
				this.parent = parent;
			}

			// Token: 0x06000D94 RID: 3476 RVA: 0x00040527 File Offset: 0x0003E927
			public IDisposable Run()
			{
				this.list = new List<T>(this.parent.count);
				return this.parent.source.Subscribe(this);
			}

			// Token: 0x06000D95 RID: 3477 RVA: 0x00040550 File Offset: 0x0003E950
			public override void OnNext(T value)
			{
				this.list.Add(value);
				if (this.list.Count == this.parent.count)
				{
					this.observer.OnNext(this.list);
					this.list = new List<T>(this.parent.count);
				}
			}

			// Token: 0x06000D96 RID: 3478 RVA: 0x000405B0 File Offset: 0x0003E9B0
			public override void OnError(Exception error)
			{
				try
				{
					this.observer.OnError(error);
				}
				finally
				{
					base.Dispose();
				}
			}

			// Token: 0x06000D97 RID: 3479 RVA: 0x000405E8 File Offset: 0x0003E9E8
			public override void OnCompleted()
			{
				if (this.list.Count > 0)
				{
					this.observer.OnNext(this.list);
				}
				try
				{
					this.observer.OnCompleted();
				}
				finally
				{
					base.Dispose();
				}
			}

			// Token: 0x040007B0 RID: 1968
			private readonly BufferObservable<T> parent;

			// Token: 0x040007B1 RID: 1969
			private List<T> list;
		}

		// Token: 0x02000250 RID: 592
		private class Buffer_ : OperatorObserverBase<T, IList<T>>
		{
			// Token: 0x06000D98 RID: 3480 RVA: 0x00040644 File Offset: 0x0003EA44
			public Buffer_(BufferObservable<T> parent, IObserver<IList<T>> observer, IDisposable cancel) : base(observer, cancel)
			{
				this.parent = parent;
			}

			// Token: 0x06000D99 RID: 3481 RVA: 0x00040655 File Offset: 0x0003EA55
			public IDisposable Run()
			{
				this.q = new Queue<List<T>>();
				this.index = -1;
				return this.parent.source.Subscribe(this);
			}

			// Token: 0x06000D9A RID: 3482 RVA: 0x0004067C File Offset: 0x0003EA7C
			public override void OnNext(T value)
			{
				this.index++;
				if (this.index % this.parent.skip == 0)
				{
					this.q.Enqueue(new List<T>(this.parent.count));
				}
				int count = this.q.Count;
				for (int i = 0; i < count; i++)
				{
					List<T> list = this.q.Dequeue();
					list.Add(value);
					if (list.Count == this.parent.count)
					{
						this.observer.OnNext(list);
					}
					else
					{
						this.q.Enqueue(list);
					}
				}
			}

			// Token: 0x06000D9B RID: 3483 RVA: 0x00040730 File Offset: 0x0003EB30
			public override void OnError(Exception error)
			{
				try
				{
					this.observer.OnError(error);
				}
				finally
				{
					base.Dispose();
				}
			}

			// Token: 0x06000D9C RID: 3484 RVA: 0x00040768 File Offset: 0x0003EB68
			public override void OnCompleted()
			{
				foreach (List<T> value in this.q)
				{
					this.observer.OnNext(value);
				}
				try
				{
					this.observer.OnCompleted();
				}
				finally
				{
					base.Dispose();
				}
			}

			// Token: 0x040007B2 RID: 1970
			private readonly BufferObservable<T> parent;

			// Token: 0x040007B3 RID: 1971
			private Queue<List<T>> q;

			// Token: 0x040007B4 RID: 1972
			private int index;
		}

		// Token: 0x02000251 RID: 593
		private class BufferT : OperatorObserverBase<T, IList<T>>
		{
			// Token: 0x06000D9D RID: 3485 RVA: 0x000407F0 File Offset: 0x0003EBF0
			public BufferT(BufferObservable<T> parent, IObserver<IList<T>> observer, IDisposable cancel) : base(observer, cancel)
			{
				this.parent = parent;
			}

			// Token: 0x06000D9E RID: 3486 RVA: 0x0004080C File Offset: 0x0003EC0C
			public IDisposable Run()
			{
				this.list = new List<T>();
				IDisposable disposable = Observable.Interval(this.parent.timeSpan, this.parent.scheduler).Subscribe(new BufferObservable<T>.BufferT.Buffer(this));
				IDisposable disposable2 = this.parent.source.Subscribe(this);
				return StableCompositeDisposable.Create(disposable, disposable2);
			}

			// Token: 0x06000D9F RID: 3487 RVA: 0x00040864 File Offset: 0x0003EC64
			public override void OnNext(T value)
			{
				object obj = this.gate;
				lock (obj)
				{
					this.list.Add(value);
				}
			}

			// Token: 0x06000DA0 RID: 3488 RVA: 0x000408A8 File Offset: 0x0003ECA8
			public override void OnError(Exception error)
			{
				try
				{
					this.observer.OnError(error);
				}
				finally
				{
					base.Dispose();
				}
			}

			// Token: 0x06000DA1 RID: 3489 RVA: 0x000408E0 File Offset: 0x0003ECE0
			public override void OnCompleted()
			{
				object obj = this.gate;
				List<T> value;
				lock (obj)
				{
					value = this.list;
				}
				this.observer.OnNext(value);
				try
				{
					this.observer.OnCompleted();
				}
				finally
				{
					base.Dispose();
				}
			}

			// Token: 0x040007B5 RID: 1973
			private static readonly T[] EmptyArray = new T[0];

			// Token: 0x040007B6 RID: 1974
			private readonly BufferObservable<T> parent;

			// Token: 0x040007B7 RID: 1975
			private readonly object gate = new object();

			// Token: 0x040007B8 RID: 1976
			private List<T> list;

			// Token: 0x02000252 RID: 594
			private class Buffer : IObserver<long>
			{
				// Token: 0x06000DA3 RID: 3491 RVA: 0x0004095D File Offset: 0x0003ED5D
				public Buffer(BufferObservable<T>.BufferT parent)
				{
					this.parent = parent;
				}

				// Token: 0x06000DA4 RID: 3492 RVA: 0x0004096C File Offset: 0x0003ED6C
				public void OnNext(long value)
				{
					bool flag = false;
					object gate = this.parent.gate;
					List<T> list;
					lock (gate)
					{
						list = this.parent.list;
						if (list.Count != 0)
						{
							this.parent.list = new List<T>();
						}
						else
						{
							flag = true;
						}
					}
					this.parent.observer.OnNext((!flag) ? list : BufferObservable<T>.BufferT.EmptyArray);
				}

				// Token: 0x06000DA5 RID: 3493 RVA: 0x000409FC File Offset: 0x0003EDFC
				public void OnError(Exception error)
				{
				}

				// Token: 0x06000DA6 RID: 3494 RVA: 0x000409FE File Offset: 0x0003EDFE
				public void OnCompleted()
				{
				}

				// Token: 0x040007B9 RID: 1977
				private BufferObservable<T>.BufferT parent;
			}
		}

		// Token: 0x02000253 RID: 595
		private class BufferTS : OperatorObserverBase<T, IList<T>>
		{
			// Token: 0x06000DA7 RID: 3495 RVA: 0x00040A00 File Offset: 0x0003EE00
			public BufferTS(BufferObservable<T> parent, IObserver<IList<T>> observer, IDisposable cancel) : base(observer, cancel)
			{
				this.parent = parent;
			}

			// Token: 0x06000DA8 RID: 3496 RVA: 0x00040A1C File Offset: 0x0003EE1C
			public IDisposable Run()
			{
				this.totalTime = TimeSpan.Zero;
				this.nextShift = this.parent.timeShift;
				this.nextSpan = this.parent.timeSpan;
				this.q = new Queue<IList<T>>();
				this.timerD = new SerialDisposable();
				this.q.Enqueue(new List<T>());
				this.CreateTimer();
				IDisposable disposable = this.parent.source.Subscribe(this);
				return StableCompositeDisposable.Create(disposable, this.timerD);
			}

			// Token: 0x06000DA9 RID: 3497 RVA: 0x00040AA0 File Offset: 0x0003EEA0
			private void CreateTimer()
			{
				SingleAssignmentDisposable singleAssignmentDisposable = new SingleAssignmentDisposable();
				this.timerD.Disposable = singleAssignmentDisposable;
				bool isSpan = false;
				bool isShift = false;
				if (this.nextSpan == this.nextShift)
				{
					isSpan = true;
					isShift = true;
				}
				else if (this.nextSpan < this.nextShift)
				{
					isSpan = true;
				}
				else
				{
					isShift = true;
				}
				TimeSpan t = (!isSpan) ? this.nextShift : this.nextSpan;
				TimeSpan dueTime = t - this.totalTime;
				this.totalTime = t;
				if (isSpan)
				{
					this.nextSpan += this.parent.timeShift;
				}
				if (isShift)
				{
					this.nextShift += this.parent.timeShift;
				}
				singleAssignmentDisposable.Disposable = this.parent.scheduler.Schedule(dueTime, delegate()
				{
					object obj = this.gate;
					lock (obj)
					{
						if (isShift)
						{
							List<T> item = new List<T>();
							this.q.Enqueue(item);
						}
						if (isSpan)
						{
							IList<T> value = this.q.Dequeue();
							this.observer.OnNext(value);
						}
					}
					this.CreateTimer();
				});
			}

			// Token: 0x06000DAA RID: 3498 RVA: 0x00040BD0 File Offset: 0x0003EFD0
			public override void OnNext(T value)
			{
				object obj = this.gate;
				lock (obj)
				{
					foreach (IList<T> list in this.q)
					{
						list.Add(value);
					}
				}
			}

			// Token: 0x06000DAB RID: 3499 RVA: 0x00040C54 File Offset: 0x0003F054
			public override void OnError(Exception error)
			{
				try
				{
					this.observer.OnError(error);
				}
				finally
				{
					base.Dispose();
				}
			}

			// Token: 0x06000DAC RID: 3500 RVA: 0x00040C8C File Offset: 0x0003F08C
			public override void OnCompleted()
			{
				object obj = this.gate;
				lock (obj)
				{
					foreach (IList<T> value in this.q)
					{
						this.observer.OnNext(value);
					}
					try
					{
						this.observer.OnCompleted();
					}
					finally
					{
						base.Dispose();
					}
				}
			}

			// Token: 0x040007BA RID: 1978
			private readonly BufferObservable<T> parent;

			// Token: 0x040007BB RID: 1979
			private readonly object gate = new object();

			// Token: 0x040007BC RID: 1980
			private Queue<IList<T>> q;

			// Token: 0x040007BD RID: 1981
			private TimeSpan totalTime;

			// Token: 0x040007BE RID: 1982
			private TimeSpan nextShift;

			// Token: 0x040007BF RID: 1983
			private TimeSpan nextSpan;

			// Token: 0x040007C0 RID: 1984
			private SerialDisposable timerD;
		}

		// Token: 0x02000254 RID: 596
		private class BufferTC : OperatorObserverBase<T, IList<T>>
		{
			// Token: 0x06000DAD RID: 3501 RVA: 0x00040DDC File Offset: 0x0003F1DC
			public BufferTC(BufferObservable<T> parent, IObserver<IList<T>> observer, IDisposable cancel) : base(observer, cancel)
			{
				this.parent = parent;
			}

			// Token: 0x06000DAE RID: 3502 RVA: 0x00040DF8 File Offset: 0x0003F1F8
			public IDisposable Run()
			{
				this.list = new List<T>();
				this.timerId = 0L;
				this.timerD = new SerialDisposable();
				this.CreateTimer();
				IDisposable disposable = this.parent.source.Subscribe(this);
				return StableCompositeDisposable.Create(disposable, this.timerD);
			}

			// Token: 0x06000DAF RID: 3503 RVA: 0x00040E48 File Offset: 0x0003F248
			private void CreateTimer()
			{
				long currentTimerId = this.timerId;
				SingleAssignmentDisposable singleAssignmentDisposable = new SingleAssignmentDisposable();
				this.timerD.Disposable = singleAssignmentDisposable;
				ISchedulerPeriodic schedulerPeriodic = this.parent.scheduler as ISchedulerPeriodic;
				if (schedulerPeriodic != null)
				{
					singleAssignmentDisposable.Disposable = schedulerPeriodic.SchedulePeriodic(this.parent.timeSpan, delegate
					{
						this.OnNextTick(currentTimerId);
					});
				}
				else
				{
					singleAssignmentDisposable.Disposable = this.parent.scheduler.Schedule(this.parent.timeSpan, delegate(Action<TimeSpan> self)
					{
						this.OnNextRecursive(currentTimerId, self);
					});
				}
			}

			// Token: 0x06000DB0 RID: 3504 RVA: 0x00040EEC File Offset: 0x0003F2EC
			private void OnNextTick(long currentTimerId)
			{
				bool flag = false;
				object obj = this.gate;
				List<T> list;
				lock (obj)
				{
					if (currentTimerId != this.timerId)
					{
						return;
					}
					list = this.list;
					if (list.Count != 0)
					{
						this.list = new List<T>();
					}
					else
					{
						flag = true;
					}
				}
				this.observer.OnNext((!flag) ? list : BufferObservable<T>.BufferTC.EmptyArray);
			}

			// Token: 0x06000DB1 RID: 3505 RVA: 0x00040F78 File Offset: 0x0003F378
			private void OnNextRecursive(long currentTimerId, Action<TimeSpan> self)
			{
				bool flag = false;
				object obj = this.gate;
				List<T> list;
				lock (obj)
				{
					if (currentTimerId != this.timerId)
					{
						return;
					}
					list = this.list;
					if (list.Count != 0)
					{
						this.list = new List<T>();
					}
					else
					{
						flag = true;
					}
				}
				this.observer.OnNext((!flag) ? list : BufferObservable<T>.BufferTC.EmptyArray);
				self(this.parent.timeSpan);
			}

			// Token: 0x06000DB2 RID: 3506 RVA: 0x00041014 File Offset: 0x0003F414
			public override void OnNext(T value)
			{
				List<T> list = null;
				object obj = this.gate;
				lock (obj)
				{
					this.list.Add(value);
					if (this.list.Count == this.parent.count)
					{
						list = this.list;
						this.list = new List<T>();
						this.timerId += 1L;
						this.CreateTimer();
					}
				}
				if (list != null)
				{
					this.observer.OnNext(list);
				}
			}

			// Token: 0x06000DB3 RID: 3507 RVA: 0x000410B0 File Offset: 0x0003F4B0
			public override void OnError(Exception error)
			{
				try
				{
					this.observer.OnError(error);
				}
				finally
				{
					base.Dispose();
				}
			}

			// Token: 0x06000DB4 RID: 3508 RVA: 0x000410E8 File Offset: 0x0003F4E8
			public override void OnCompleted()
			{
				object obj = this.gate;
				List<T> value;
				lock (obj)
				{
					this.timerId += 1L;
					value = this.list;
				}
				this.observer.OnNext(value);
				try
				{
					this.observer.OnCompleted();
				}
				finally
				{
					base.Dispose();
				}
			}

			// Token: 0x040007C1 RID: 1985
			private static readonly T[] EmptyArray = new T[0];

			// Token: 0x040007C2 RID: 1986
			private readonly BufferObservable<T> parent;

			// Token: 0x040007C3 RID: 1987
			private readonly object gate = new object();

			// Token: 0x040007C4 RID: 1988
			private List<T> list;

			// Token: 0x040007C5 RID: 1989
			private long timerId;

			// Token: 0x040007C6 RID: 1990
			private SerialDisposable timerD;
		}
	}
}
